/**
 在 JavaScript 的响应式系统中，监听属性变化是实现动态更新和响应式编程的关键功能。在 Vue 3 中，监听属性变化主要通过  `watch`  和  `computed`  函数来实现。以下是对 Vue 3 中监听属性变化的说明总结：

1. watch 函数
 `watch`  函数用于侦听一个或多个响应式数据的变化，并在变化时执行指定的回调函数。

 基本用法：
import { reactive, watch } from 'vue';

const state = reactive({ count: 0 });

watch(
  () => state.count, // 侦听的响应式属性
  (newValue, oldValue) => {
    console.log(`Count changed from ${oldValue} to ${newValue}`);
  }
);

// 修改响应式数据
state.count++; // 当 count 变化时，回调会被触发
2. watchEffect 函数
 `watchEffect`  是一个更简化的 API，用于自动侦听响应式数据的变化。它会立即执行传入的函数，并在依赖的响应式数据变化时重新执行。

 示例：
import { reactive, watchEffect } from 'vue';

const state = reactive({ count: 0 });

watchEffect(() => {
  console.log(`Count is: ${state.count}`);
});

// 修改响应式数据
state.count++; // 当 count 变化时，watchEffect 会被重新执行
3. computed 函数
 `computed`  函数用于创建计算属性，它会自动依赖于其使用的响应式数据，并在这些数据变化时重新计算值。

 示例：
import { reactive, computed } from 'vue';

const state = reactive({ count: 0 });
const doubleCount = computed(() => state.count * 2);

// 使用计算属性
console.log(doubleCount.value); // 输出初始值
state.count++; // 修改 count
console.log(doubleCount.value); // 输出更新后的值
4. 深度监听
对于嵌套对象的变化，可以使用  `deep`  选项来进行深度监听。

 示例：
const state = reactive({ user: { name: 'Alice' } });

watch(
  () => state.user,
  (newValue, oldValue) => {
    console.log('User object changed:', newValue);
  },
  { deep: true } // 深度监听
);

// 修改嵌套属性
state.user.name = 'Bob'; // 当 name 变化时，回调会被触发
5. 立即执行
可以设置  `immediate`  选项，使得在侦听器被创建时立即执行一次回调。

 示例：
watch(
  () => state.count,
  (newValue, oldValue) => {
    console.log(`Count changed from ${oldValue} to ${newValue}`);
  },
  { immediate: true } // 立即执行
);
总结
在 Vue 3 中，监听属性变化的主要工具是  `watch`  和  `computed`  函数。 `watch`  用于侦听特定的响应式数据变化，而  `watchEffect`  则自动侦听依赖。通过这些 API，开发者可以轻松实现对数据变化的响应，提高应用的动态性和用户体验。理解如何监听属性变化是掌握 Vue 3 响应式系统的重要部分。
 */
class Depend {
  constructor() {
    this.reactiveFns = []
  }
  // 添加依赖
  addDepend(reactiveFn) {
    if (reactiveFn) {
      this.reactiveFns.push(reactiveFn)
    }
  }

  // notify: 通知更新
  notify() {
    this.reactiveFns.forEach((fn) => {
      fn()
    })
  }
}

// 设置一个专门执行响应式函数的一个函数
const dep = new Depend()
function watchFn(fn) {
  dep.addDepend(fn)
  fn()
}

const obj = {
  name: 'depend-name',
  age: 18
}

// 方案一: Object.defineProperty() -> Vue2
Object.keys(obj).forEach((key) => {
  let value = obj[key]

  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newValue) {
      value = newValue
      dep.notify()
    }
  })
})

watchFn(function foo() {
  console.log("foo:", obj.name)
  console.log("foo", obj.age)
  console.log("foo function")
})


watchFn(function bar() {
  console.log("bar:", obj.name + " hello")
  console.log("bar:", obj.age + 10)
  console.log("bar function")
})

// 修改obj的属性
console.log("name发生变化-----------------------")
obj.name = "kobe"

console.log("age发生变化-----------------------")
obj.age = 20

console.log("name发生变化-----------------------")
obj.name = "james"
